package cool.mtc.minghe.service.service.sys.dict.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cool.mtc.core.exception.ServiceException;
import cool.mtc.core.page.PageData;
import cool.mtc.minghe.data.entity.sys.dict.DictDO;
import cool.mtc.minghe.data.entity.sys.dict.DictTypeDO;
import cool.mtc.minghe.data.model.base.Dict;
import cool.mtc.minghe.data.model.sys.dict.type.dto.DictTypeDTO;
import cool.mtc.minghe.data.model.sys.dict.type.dto.DictTypeListDTO;
import cool.mtc.minghe.data.model.sys.dict.type.form.DictTypeForm;
import cool.mtc.minghe.data.model.sys.dict.type.query.DictTypeQuery;
import cool.mtc.minghe.service.manager.sys.dict.DictTypeManager;
import cool.mtc.minghe.service.mapper.sys.dict.DictMapper;
import cool.mtc.minghe.service.mapper.sys.dict.DictTypeMapper;
import cool.mtc.minghe.service.service.BaseServiceImpl;
import cool.mtc.minghe.service.service.sys.dict.DictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author 明河
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DictTypeServiceImpl extends BaseServiceImpl implements DictTypeService {
    private final DictTypeMapper dictTypeMapper;
    private final DictMapper dictMapper;

    private final DictTypeManager dictTypeManager;

    @Override
    @Transactional
    public long insert(DictTypeForm form) {
        DictTypeDO dictTypeDO = form.transToDO();
        dictTypeDO.setCreator(userId());
        dictTypeMapper.insert(dictTypeDO);
        dictTypeManager.clearDictCache();
        return dictTypeDO.getId();
    }

    @Override
    @Transactional
    public void update(DictTypeForm form) {
        DictTypeDO dictTypeDO = dictTypeMapper.selectById(form.getId());
        if (null == dictTypeDO) {
            throw new ServiceException("dict_type.data.expired");
        }
        form.updateDO(dictTypeDO);
        dictTypeMapper.updateById(dictTypeDO);
        dictTypeManager.clearDictCache();
    }

    @Override
    @Transactional
    public void delete(Long id) {
        if (null == id) {
            return;
        }
        DictTypeDO dictTypeDO = dictTypeMapper.selectById(id);
        if (null == dictTypeDO) {
            return;
        }
        this.handleCheckCanDelete(dictTypeDO);
        dictTypeMapper.deleteById(id);
        dictTypeManager.clearDictCache();
    }

    /**
     * 检查是否可以删除
     */
    private void handleCheckCanDelete(DictTypeDO dictTypeDO) {
        if (Boolean.TRUE.equals(dictTypeDO.getPreset())) {
            throw new ServiceException("preset.delete.not_allow");
        }
        QueryWrapper<DictDO> wrapper = new QueryWrapper<>();
        wrapper.eq("dict_type_id", dictTypeDO.getId());
        long count = dictMapper.selectCount(wrapper);
        if (0 == count) {
            return;
        }
        throw new ServiceException("dict_type.delete.used");
    }

    @Override
    public PageData<DictTypeListDTO> pageList(DictTypeQuery query) {
        OrderItem[] items = {
                OrderItem.asc("DT.order_index"),
        };
        Page<DictTypeListDTO> page = dictTypeMapper.pageList(super.pageParam(items), query);
        return PageData.of(page.getRecords(), page.getTotal());
    }

    @Override
    public DictTypeDTO info(Long id) {
        if (null == id) {
            return null;
        }
        return dictTypeMapper.getById(id);
    }

    @Override
    public List<Dict> dictList() {
        return dictTypeManager.listDict();
    }

    @Override
    @Transactional
    public long saveWithUpdate(DictTypeDO dictTypeDO) {
        QueryWrapper<DictTypeDO> wrapper = new QueryWrapper<>();
        wrapper.eq("code", dictTypeDO.getCode());
        DictTypeDO existDictTypeDO = dictTypeMapper.selectOne(wrapper);
        if (null == existDictTypeDO) {
            dictTypeMapper.insert(dictTypeDO);
            return dictTypeDO.getId();
        }
        BeanUtils.copyProperties(dictTypeDO, existDictTypeDO, "id", "code");
        dictTypeMapper.updateById(existDictTypeDO);
        return existDictTypeDO.getId();
    }
}
